package com.docmgmt.mvp.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.docmgmt.mvp.constant.PermissionConstants;
import com.docmgmt.mvp.entity.*;
import com.docmgmt.mvp.mapper.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 权限服务（v3.0 RBAC核心）
 *
 * 基于10-模式库的模式1：5步权限检查
 * 1. 查询用户角色
 * 2. 查询角色权限（含继承链）
 * 3. 查询用户直接权限
 * 4. 资源所有者检查
 * 5. 权限匹配
 *
 * 角色继承链（低级别继承高级别权限）：
 * member (1) → dept_admin (5) → senior_manager (7) → system_admin (10)
 *
 * @author Dora
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PermissionService {

    private final UserMapper userMapper;
    private final RoleMapper roleMapper;
    private final PermissionMapper permissionMapper;
    private final FileMapper fileMapper;
    private final FolderMapper folderMapper;
    private final AiDialogMapper aiDialogMapper;
    // private final TempPermissionMapper tempPermissionMapper; // TODO: Create this mapper

    /**
     * 五步权限检查（核心方法）
     *
     * @param userId   用户ID
     * @param resource 资源标识（如 "file:123", "folder:456", "kb"）
     * @param action   操作类型（read/create/update/delete/manage）
     * @return 是否有权限
     */
    public boolean checkPermission(Long userId, String resource, String action) {
        log.debug("权限检查: userId={}, resource={}, action={}", userId, resource, action);

        // Step 1: 查询用户角色
        List<RoleEntity> roles = roleMapper.selectRolesByUserId(userId);
        if (roles.isEmpty()) {
            log.warn("用户 {} 没有任何角色", userId);
            return false;
        }

        // Step 2: 查询角色权限（含继承链）
        Set<String> permissions = new HashSet<>();
        for (RoleEntity role : roles) {
            permissions.addAll(getPermissionsWithInheritance(role.getRoleCode()));
        }

        // Step 3: 查询用户直接权限（优先级最高）
        List<PermissionEntity> directPermissions = permissionMapper.selectDirectPermissionsByUserId(userId);
        permissions.addAll(directPermissions.stream()
            .map(PermissionEntity::getPermissionCode)
            .collect(Collectors.toSet()));

        // Step 3.5: 临时权限检查（如临时文件夹权限）
        if (checkTempPermission(userId, resource, action)) {
            log.debug("用户 {} 拥有资源 {} 的临时{}权限", userId, resource, action);
            return true;
        }

        // Step 4: 资源所有者检查
        if (isResourceOwner(userId, resource)) {
            log.debug("用户 {} 是资源 {} 的所有者，自动授权", userId, resource);
            return true;
        }

        // Step 5: 权限匹配
        String resourceType = extractResourceType(resource);
        String requiredPerm = mapToPermissionCode(resourceType, action);

        boolean hasPermission = permissions.contains(requiredPerm) || permissions.contains("*:*");
        log.debug("权限检查结果: userId={}, resource={}, action={}, requiredPerm={}, hasPermission={}",
            userId, resource, action, requiredPerm, hasPermission);

        return hasPermission;
    }

    /**
     * 获取角色权限（含继承链）
     *
     * 继承规则：
     * - member继承dept_admin的权限
     * - dept_admin继承senior_manager的权限
     * - senior_manager继承system_admin的权限
     */
    @Cacheable(value = "rolePermissions", key = "#roleCode")
    public Set<String> getPermissionsWithInheritance(String roleCode) {
        Set<String> allPermissions = new HashSet<>();

        // 当前角色的权限
        RoleEntity role = roleMapper.selectByRoleCode(roleCode);
        if (role == null) {
            return allPermissions;
        }

        List<PermissionEntity> permissions = permissionMapper.selectPermissionsByRoleId(role.getId());
        allPermissions.addAll(permissions.stream()
            .map(PermissionEntity::getPermissionCode)
            .collect(Collectors.toSet()));

        // 递归获取父角色权限
        if (role.getParentRoleCode() != null) {
            allPermissions.addAll(getPermissionsWithInheritance(role.getParentRoleCode()));
        }

        return allPermissions;
    }

    /**
     * 检查用户是否为资源所有者（v3.0完整实现）
     *
     * @param userId   用户ID
     * @param resource 资源标识（如 "file:123", "folder:456", "dialog:789"）
     * @return 是否为所有者
     */
    private boolean isResourceOwner(Long userId, String resource) {
        // 解析资源类型和ID
        String[] parts = resource.split(":");
        if (parts.length != 2) {
            return false;
        }

        String resourceType = parts[0];
        Long resourceId;
        try {
            resourceId = Long.parseLong(parts[1]);
        } catch (NumberFormatException e) {
            return false;
        }

        // 根据资源类型检查所有权
        switch (resourceType) {
            case PermissionConstants.RESOURCE_FILE:
                // 检查文件所有者
                FileEntity file = fileMapper.selectById(resourceId);
                return file != null && file.getUploadedBy().equals(userId);

            case PermissionConstants.RESOURCE_FOLDER:
                // 检查文件夹所有者
                FolderEntity folder = folderMapper.selectById(resourceId);
                return folder != null && folder.getCreatorId().equals(userId);

            case PermissionConstants.RESOURCE_DIALOG:
                // 检查AI对话所有者
                AiDialogEntity dialog = aiDialogMapper.selectById(resourceId);
                return dialog != null && dialog.getUserId().equals(userId);

            case PermissionConstants.RESOURCE_USER:
                // 检查是否为用户本人（用户可以查看/修改自己的资料）
                return resourceId.equals(userId);

            case PermissionConstants.RESOURCE_KB:
                // 知识库通常不属于个人，由角色权限控制
                return false;

            default:
                log.warn("未知资源类型: {}", resourceType);
                return false;
        }
    }

    /**
     * 提取资源类型
     */
    private String extractResourceType(String resource) {
        if (resource.contains(":")) {
            return resource.split(":")[0];
        }
        return resource;
    }

    /**
     * 将资源类型和操作映射到数据库权限代码
     *
     * 映射规则：
     * file + create → upload_file
     * file + read → download_file（读取文件即下载）
     * file + delete → delete_file
     * file + download → download_file
     * file + share → share_file
     * folder + create → create_folder
     * kb + create → create_personal_kb（默认，可根据上下文改为dept/company）
     * kb + manage → manage_own_kb
     * dialog + create → use_ai_chat
     *
     * @param resourceType 资源类型（file/folder/kb/dialog）
     * @param action 操作类型（create/read/delete/download/share/manage）
     * @return 数据库权限代码
     */
    private String mapToPermissionCode(String resourceType, String action) {
        // 统一使用冒号格式：resource:action（v3.0标准）
        // 与PermissionConstants.java保持一致

        // 默认规则：resourceType:action
        return resourceType + ":" + action;
    }

    /**
     * 批量检查权限
     *
     * @param userId      用户ID
     * @param permissions 权限列表（格式：resource:action）
     * @return 权限检查结果（permission → hasPermission）
     */
    public Map<String, Boolean> batchCheckPermissions(Long userId, List<String> permissions) {
        Map<String, Boolean> result = new HashMap<>();

        for (String perm : permissions) {
            String[] parts = perm.split(":");
            if (parts.length == 2) {
                result.put(perm, checkPermission(userId, parts[0], parts[1]));
            }
        }

        return result;
    }

    /**
     * 获取用户的所有权限代码（用于前端权限按钮显示）
     */
    @Cacheable(value = "userPermissions", key = "#userId")
    public Set<String> getUserPermissions(Long userId) {
        List<RoleEntity> roles = roleMapper.selectRolesByUserId(userId);

        Set<String> permissions = new HashSet<>();
        for (RoleEntity role : roles) {
            permissions.addAll(getPermissionsWithInheritance(role.getRoleCode()));
        }

        // 添加用户直接权限
        List<PermissionEntity> directPermissions = permissionMapper.selectDirectPermissionsByUserId(userId);
        permissions.addAll(directPermissions.stream()
            .map(PermissionEntity::getPermissionCode)
            .collect(Collectors.toSet()));

        return permissions;
    }

    /**
     * 检查用户是否具有指定角色
     */
    public boolean hasRole(Long userId, String roleCode) {
        List<RoleEntity> roles = roleMapper.selectRolesByUserId(userId);
        return roles.stream().anyMatch(role -> role.getRoleCode().equals(roleCode));
    }

    /**
     * 获取用户最高角色等级
     */
    public Integer getMaxRoleLevel(Long userId) {
        List<RoleEntity> roles = roleMapper.selectRolesByUserId(userId);
        return roles.stream()
            .map(RoleEntity::getRoleLevel)
            .max(Integer::compareTo)
            .orElse(0);
    }

    /**
     * 检查临时权限（v3.0新增）
     *
     * 临时权限用于短期授权场景，如：
     * - 临时文件夹访问权限
     * - 临时文件编辑权限
     * - 临时知识库访问权限
     *
     * @param userId   用户ID
     * @param resource 资源标识（如 "folder:123"）
     * @param action   操作类型（read/create/update/delete）
     * @return 是否拥有临时权限
     */
    private boolean checkTempPermission(Long userId, String resource, String action) {
        // TODO: Implement when TempPermissionEntity and TempPermissionMapper are created
        // Temporarily always return false (no temp permissions)
        return false;
        /*
        // 解析资源类型和ID
        String[] parts = resource.split(":");
        if (parts.length != 2) {
            return false;
        }

        String resourceType = parts[0];
        Long resourceId;
        try {
            resourceId = Long.parseLong(parts[1]);
        } catch (NumberFormatException e) {
            return false;
        }

        // 查询临时权限表
        LambdaQueryWrapper<TempPermissionEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TempPermissionEntity::getUserId, userId)
               .eq(TempPermissionEntity::getResourceType, resourceType)
               .eq(TempPermissionEntity::getResourceId, resourceId)
               .eq(TempPermissionEntity::getPermissionType, action)
               .gt(TempPermissionEntity::getExpiresAt, LocalDateTime.now());

        TempPermissionEntity tempPerm = tempPermissionMapper.selectOne(wrapper);

        if (tempPerm != null) {
            log.debug("用户 {} 拥有资源 {}:{} 的临时{}权限，到期时间: {}",
                    userId, resourceType, resourceId, action, tempPerm.getExpiresAt());
            return true;
        }

        return false;
        */
    }

    /**
     * 授予临时权限（管理员或资源所有者可调用）
     *
     * @param userId       被授权用户ID
     * @param resourceType 资源类型（file/folder/kb）
     * @param resourceId   资源ID
     * @param action       操作类型（read/create/update/delete）
     * @param expiresAt    过期时间
     * @param grantedBy    授权人ID
     */
    public void grantTempPermission(Long userId, String resourceType, Long resourceId,
                                     String action, LocalDateTime expiresAt, Long grantedBy) {
        log.info("授予临时权限: userId={}, resource={}:{}, action={}, expiresAt={}, grantedBy={}",
                userId, resourceType, resourceId, action, expiresAt, grantedBy);
        // TODO: Implement when TempPermissionEntity and TempPermissionMapper are created
        log.warn("临时权限功能暂未实现（TODO: TempPermissionEntity/Mapper）");
        /*
        TempPermissionEntity tempPerm = new TempPermissionEntity();
        tempPerm.setUserId(userId);
        tempPerm.setResourceType(resourceType);
        tempPerm.setResourceId(resourceId);
        tempPerm.setPermissionType(action);
        tempPerm.setExpiresAt(expiresAt);
        tempPerm.setGrantedBy(grantedBy);

        tempPermissionMapper.insert(tempPerm);
        */
    }

    /**
     * 撤销临时权限
     *
     * @param userId       被撤销用户ID
     * @param resourceType 资源类型
     * @param resourceId   资源ID
     * @param action       操作类型
     */
    public void revokeTempPermission(Long userId, String resourceType, Long resourceId, String action) {
        log.info("撤销临时权限: userId={}, resource={}:{}, action={}", userId, resourceType, resourceId, action);
        // TODO: Implement when TempPermissionEntity and TempPermissionMapper are created
        log.warn("临时权限功能暂未实现（TODO: TempPermissionEntity/Mapper）");
        /*
        LambdaQueryWrapper<TempPermissionEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TempPermissionEntity::getUserId, userId)
               .eq(TempPermissionEntity::getResourceType, resourceType)
               .eq(TempPermissionEntity::getResourceId, resourceId)
               .eq(TempPermissionEntity::getPermissionType, action);

        tempPermissionMapper.delete(wrapper);
        */
    }

    /**
     * 清理过期的临时权限（定时任务调用）
     */
    public int cleanExpiredTempPermissions() {
        // TODO: Implement when TempPermissionEntity and TempPermissionMapper are created
        log.debug("临时权限清理功能暂未实现（TODO: TempPermissionEntity/Mapper）");
        return 0;
        /*
        LambdaQueryWrapper<TempPermissionEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.lt(TempPermissionEntity::getExpiresAt, LocalDateTime.now());

        int count = tempPermissionMapper.delete(wrapper);
        if (count > 0) {
            log.info("清理了 {} 条过期的临时权限", count);
        }

        return count;
        */
    }
}
